#ifndef UINT_BYTEBUFFER_H
#define UINT_BYTEBUFFER_H

#include "../Type.h"
#include <string>
#include <vector>
#include <list>
#include <set>
#include <map>
#include <assert.h>

class CBuffer
{
#define DEFAULT_BUFFER_SIZE         2048
#define DEFAULT_MAX_BUFFER_SIZE     6549500
public:
	CBuffer( uint bufferSize = DEFAULT_BUFFER_SIZE )                       : _rpos(0), _wpos(0)     { 
		bufferSize = ( (bufferSize - 1) / DEFAULT_BUFFER_SIZE + 1) * DEFAULT_BUFFER_SIZE;
		_pstorage = (byte*)malloc(bufferSize);
		if ( _pstorage != NULL )
			_bufflen = bufferSize;
	}

	void ClearUp() {
		void* pTemp = realloc(_pstorage, DEFAULT_BUFFER_SIZE); 
		if ( pTemp ){
			_pstorage = (byte(*))pTemp;
			_bufflen = DEFAULT_BUFFER_SIZE;
		}
		_rpos = _wpos = 0; 
	}
	void Peek(byte *dest, size_t len) { 
		if ( _rpos  + len  > _wpos )
			throw 1;
		memcpy(dest, &_pstorage[_rpos], len); 
	}

	CBuffer& operator>>(bool          &value) { byte tmp; Read((byte*)&tmp,sizeof(tmp)); value = tmp==0? false: true; return *this; }
	CBuffer& operator>>(byte          &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(ushort        &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(uint          &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(uint64        &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(char          &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(short         &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(int           &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(int64         &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(float         &value) { Read((byte*)&value,sizeof(value));                return *this; }
	CBuffer& operator>>(double        &value) { Read((byte*)&value,sizeof(value));                return *this; }

	CBuffer& operator<<(const bool    &value) { byte tmp = value? 1: 0; Write((const byte*)&tmp,sizeof(tmp)); return *this; }
	CBuffer& operator<<(const char    &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const short   &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const int     &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const int64   &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const byte    &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const uint    &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const ushort  &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const uint64  &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const float   &value) { Write((const byte*)&value,sizeof(value));         return *this; }
	CBuffer& operator<<(const double  &value) { Write((const byte*)&value,sizeof(value));         return *this; }

	CBuffer &operator<<(const std::string &value) { 
		uint len = value.size(); *this<<len;
		Write((const byte*)value.c_str(), len);  
		return *this;
	}
	CBuffer &operator>>(std::string& value){
		uint len = 0; *this>>len; value.resize(len+1, '\0');
		for ( uint i = 0; i < len; i++ ) Read((byte*)&value[i], sizeof(value[i]));
		return *this;
	}
	CBuffer& operator<<(const CBuffer &b){
		uint len = b.size(); *this<<len;
		Write((const byte*)b.contents(), len);  
		return *this;
	}
	CBuffer& operator>>(CBuffer &b){
		uint len; *this>>len;
		b.Write((const byte*)contents(), len);  
		return *this;
	}
	size_t rpos()                   { return _rpos; };
	size_t rpos(size_t rpos_)       { _rpos = rpos_;return _rpos;};
	size_t wpos()                   { return _wpos; }
	size_t wpos(size_t wpos_)       { _wpos = wpos_; return _wpos; }

	const byte *contents() const     { return &_pstorage[_rpos]; }
	size_t size() const              { return _wpos - _rpos; }
	bool empty() const               { return _wpos == _rpos; }

	const byte* GetBuff() const      { return _pstorage; }
	uint GetBuffLen()                { return _bufflen; }

	void Write(const byte *src, size_t cnt)	{
		if ( cnt == 0 ) return;
		if ( _bufflen > DEFAULT_MAX_BUFFER_SIZE )
			throw 1;
		uint remaider = _bufflen-_wpos-1;
		if ( _bufflen <= _wpos+cnt ){
			uint bufferSize = ( (cnt - 1) / DEFAULT_BUFFER_SIZE + 1) * DEFAULT_BUFFER_SIZE + _bufflen;
			void* pTemp = realloc(_pstorage, bufferSize); 
			if ( pTemp ){
				_pstorage = (byte(*))pTemp;
				_bufflen = bufferSize;
			}
			else
				throw 2;
		}

		memcpy(&_pstorage[_wpos], src, cnt);
		_wpos += cnt;
	}
	void Read(byte *dest, size_t len) { 
		if ( _rpos >= _wpos )
			throw 3;
		if ( _rpos  + len  > _wpos )
			throw 4;
		memcpy(dest, &_pstorage[_rpos], len); 
		_rpos += len; 
	}

private:
	bool operator ==(const CBuffer& anothor) const
	{
		return true;
	}
	bool operator !=(const CBuffer& anothor) const
	{
		return false;
	}
	bool operator <(const CBuffer& anothor) const
	{
		return false;
	}

protected:

	size_t _rpos, _wpos;
	byte* _pstorage;
	uint _bufflen;
};

template <typename T> CBuffer &operator<<(CBuffer &b, std::vector<T> v)
{
    b << (uint)v.size(); if ( v.size() <= 0 ) return b;
    for ( size_t i = 0; i < v.size(); i++ ){ b << v[i]; }
    return b;
}

template <typename T> CBuffer &operator>>(CBuffer &b, std::vector<T> &v)
{
    uint vsize;
    b >> vsize; if ( vsize <= 0 ) return b;
    v.clear();v.resize(vsize);
	for ( size_t i = 0; i < vsize; i++ ){ b >> v[i]; }
    return b;
}

template <typename T> CBuffer &operator<<(CBuffer &b, std::list<T> v)
{
    b << (uint)v.size();
	if ( v.size() <= 0 ) return b;
    for (typename std::list<T>::iterator i = v.begin(); i != v.end(); i++)
    {
        b << *i;
    }
    return b;
}

template <typename T> CBuffer &operator>>(CBuffer &b, std::list<T> &v)
{
    uint vsize;
    b >> vsize; if ( vsize <= 0 ) return b;
    v.clear();
    while(vsize--)
    {
        T t;
        b >> t;
        v.push_back(t);
    }
    return b;
}

template <typename T> CBuffer &operator<<(CBuffer &b, std::set<T> &s)
{
	uint ssize = (uint)s.size(); b<<ssize; if ( ssize <= 0 ) return b;
	for (typename std::set<T>::iterator i = s.begin(); i != s.end(); i++)
		b<<*i;
	return b;
}

template <typename T> CBuffer &operator>>(CBuffer &b, std::set<T> &s)
{
	uint ssize; b>>ssize; if ( ssize <= 0 ) return b;
	while(ssize--) {
		T t; b>>t;
		s.insert(t);
	}
	return b;
}

template <typename K, typename V> CBuffer &operator<<(CBuffer &b, std::map<K, V> &m)
{
    b << (uint)m.size(); if ( m.size() <=0 ) return b;
    for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); i++)
    {
        b << i->first << i->second;
    }
    return b;
}

template <typename K, typename V> CBuffer &operator>>(CBuffer &b, std::map<K, V> &m)
{
    uint msize; b >> msize; if ( msize <= 0 ) return b;
	m.clear();
    while(msize--)
    {
        K k;
        V v;
        b >> k >> v;
        m.insert(std::pair<typename K, typename V>(k, v));
    }
    return b;
}
#endif
